package org.zebra.satoken;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;

/**
 * @author zhanghongbin
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class LoginHelper {

    public static final String LOGIN_USER_KEY = "loginUser";

    /**
     * 超级管理员ID
     */
    public static Object SUPER_ADMIN_ID = "1";

    /**
     * 登录系统 基于 设备类型
     * 针对相同用户体系不同设备
     *
     * @param loginUser 登录用户信息
     */
    public static String login(LoginUser loginUser) {
        SaLoginModel model = new SaLoginModel();
        StpUtil.login(loginUser.getLoginId(), model.setExtra(LOGIN_USER_KEY, loginUser));
        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
        ServletRequestAttributes servletRequestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        request.setAttribute(LOGIN_USER_KEY, loginUser);
        return StpUtil.getTokenValue();
    }

    /**
     * 获取用户(多级缓存)
     *
     * @return 登录对象
     */
    public static LoginUser getLoginUser() {
        ServletRequestAttributes servletRequestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        Object loginUser = request.getAttribute(LOGIN_USER_KEY);
        if (loginUser != null) {
            return (LoginUser) loginUser;
        }
        SaSession session = StpUtil.getTokenSession();
        if (ObjectUtil.isNull(session)) {
            return null;
        }
        loginUser = session.get(LOGIN_USER_KEY);
        request.setAttribute(LOGIN_USER_KEY, loginUser);
        return (LoginUser) loginUser;
    }

    /**
     * 获取用户基于token
     *
     * @param token token
     * @return 登录对象
     */
    public static LoginUser getLoginUser(String token) {
        try {
            SaSession session = StpUtil.getTokenSessionByToken(token);
            if (ObjectUtil.isNull(session)) {
                return null;
            }
            return (LoginUser) session.get(LOGIN_USER_KEY);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取登录 token
     *
     * @return
     */
    public static String getLoginToken() {
        return StpUtil.getTokenValue();
    }

    /**
     * 获取用户id
     *
     * @return 用户id
     */
    public static <T extends Serializable> T getUserId() {
        LoginUser loginUser = getLoginUser();
        if (loginUser != null) {
            return (T) loginUser.getUserId();
        }
        loginUser = (LoginUser) getExtra(LOGIN_USER_KEY);
        if (loginUser != null) {
            return (T) loginUser.getUserId();
        }
        return null;
    }

    public static String getUserName() {
        LoginUser loginUser = getLoginUser();
        if (loginUser != null) {
            return loginUser.getUserName();
        }
        loginUser = (LoginUser) getExtra(LOGIN_USER_KEY);
        if (loginUser != null) {
            return loginUser.getUserName();
        }
        return null;
    }

    public static int getUserType() {
        LoginUser loginUser = getLoginUser();
        if (loginUser != null) {
            return loginUser.getUserType();
        }
        loginUser = (LoginUser) getExtra(LOGIN_USER_KEY);
        if (loginUser != null) {
            return loginUser.getUserType();
        }
        return 1;
    }

    /**
     * 获取当前 Token 的扩展信息
     *
     * @param key 键值
     * @return 对应的扩展数据
     */
    private static Object getExtra(String key) {
        try {
            return StpUtil.getExtra(key);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 是否为超级管理员
     *
     * @param userId 用户ID
     * @return true ,false
     */
    public static <T> boolean isSuperAdmin(T userId) {
        Object userIdObj = ObjUtil.defaultIfNull(userId, "");
        return SUPER_ADMIN_ID.equals(userIdObj.toString());
    }

    /**
     * 是否为超级管理员
     *
     * @return true ,false
     */
    public static boolean isSuperAdmin() {
        return isSuperAdmin(getUserId());
    }

    /**
     * 是否是管理员(只要是超级管理员或租户管理中的一个就视为管理员)
     *
     * @return true, false
     */
    public static boolean isAdmin() {
        if (isSuperAdmin()) {
            return true;
        }
        return isTenantAdmin();
    }

    public static <T> boolean isAdmin(T userId, int userType) {
        return isSuperAdmin(userId) | isTenantAdmin(userId, userType);
    }

    /**
     * 是否管理员
     *
     * @param userId   用户id
     * @param userType 用户类型
     * @return true ,false
     */
    public static <T> boolean isTenantAdmin(T userId, int userType) {
        return !SUPER_ADMIN_ID.toString().equals(userId.toString()) && userType == 0;
    }

    /**
     * 是否为租户管理员
     *
     * @return true ,false
     */
    public static boolean isTenantAdmin() {
        Object userIdObj;
        Object userTypeObj;
        LoginUser loginUser = getLoginUser();
        if (loginUser != null) {
            userIdObj = loginUser.getUserId();
            userTypeObj = loginUser.getUserType();
        } else {
            loginUser = (LoginUser) getExtra(LOGIN_USER_KEY);
            userIdObj = loginUser.getUserId();
            userTypeObj = loginUser.getUserType();
        }
        if (userIdObj == null || userTypeObj == null) return false;
        return isTenantAdmin(userIdObj, ((Integer) userTypeObj).intValue());
    }

    /**
     * 检查当前用户是否已登录
     *
     * @return 结果
     */
    public static boolean isLogin() {
        return StpUtil.isLogin();
    }
}
